package controllers;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;

import play.Logger;
import play.Play;
import play.mvc.Controller;

public class Application extends Controller {
	
	public static final int UP = 0;
	public static final int DOWN = 1;
	
	private static final String LINE_NAME_PATTERN = "[大学科城夜快0-9a-zA-Z]+";
	public static Map<String, String> lineCodeMap;

    public static void index() {
        render();
    }
    
    public static void query(String name) throws IOException{
    	JsonObject error = new JsonObject();
    	if(StringUtils.isBlank(name)){
    		error.addProperty("error", "公交线路为空");
    		renderText(error);
    	}
    	
    	if(lineCodeMap==null){
	    	String codeMapFilePath = Play.applicationPath+File.separator+"conf"+File.separator+"code.json";
	    	FileReader fileReader = new FileReader(codeMapFilePath);
	    	JsonParser jsonParser = new JsonParser();
	    	JsonObject jsonMap = jsonParser.parse(fileReader).getAsJsonObject();
	    	Logger.debug("roots: %s",Play.applicationPath);
	    	Logger.debug("jsonMap: %s", jsonMap);
	    	lineCodeMap = new HashMap<String, String>();
	    	for (Entry<String, JsonElement> entry : jsonMap.entrySet()) {
	    		String code = entry.getValue()==null?null:entry.getValue().toString();
	    		if(code!=null){
	    			code = StringUtils.right("000"+code, 5);
	    		}
				lineCodeMap.put(entry.getKey(),code);
			}	    	
    	}
    	Logger.debug("line code: %s", lineCodeMap);
    	Pattern pattern = Pattern.compile(LINE_NAME_PATTERN);
		Matcher matcher = pattern.matcher(name);
		if(matcher.find()){
			name = matcher.group().toUpperCase();
		}else{
			error.addProperty("error", "暂不支持此线路查询1");
    		renderText(error);
		}
		
		String code = lineCodeMap.get(name);
		Logger.debug("code:%s", code);
		if(code==null){
			error.addProperty("error", "暂不支持此线路查询2");
    		renderText(error);
		}
    	
    	JsonObject result = getBusLineInfo(code);
		renderText(result);
		
    }
    
    public static void getBusLineMap() throws IOException{    	
    	HashMap<String, String> lineCodeMap = new HashMap<String, String>();
    	Set<String> lines = getAllBusLines();
    	for (String line : lines) {
    		String code = getLineCode(line);
    		lineCodeMap.put(line, code);
    		Logger.debug("%s : %s", line,code);
		}
    	renderText(lineCodeMap);
    	
    }
    
    private static String getLineCode(String line) throws IOException{
    	Document doc = Jsoup.connect("http://www.gzyyjt.cn/cn/buslinessearch.aspx?Bus="+line).get();
    	String src = doc.select("#icenter iframe").attr("src");
    	Logger.debug("src:%s", src);
    	Pattern pattern = Pattern.compile("=(\\d+)");
    	Matcher matcher = pattern.matcher(src);
    	if(matcher.find()){
    		return matcher.group(1);
    	}
    	return null;
    }
    
    private static Set<String> getAllBusLines() throws IOException{
    	Document doc = Jsoup.connect("http://bus.mapbar.com/guangzhou/line_list/").get();
    	Elements elements = doc.select("dl dd a");
    	Set<String> lines = new HashSet<String>();
    	for (Element element : elements) {
    		String text = element.text();
    		Pattern pattern = Pattern.compile(LINE_NAME_PATTERN);
    		Matcher matcher = pattern.matcher(text);
    		if(matcher.find()){
    			lines.add(matcher.group().toUpperCase());
    		}
		}
    	return lines;
    }
    
    private static JsonObject getBusLineInfo(String lineCode) throws IOException{
    	JsonObject up = getBusLineInfo(lineCode,UP); 
    	JsonObject down = getBusLineInfo(lineCode, DOWN);
    	JsonObject results = new JsonObject();
    	results.add("up", up);
    	results.add("down", down);
    	return results;
    }

	private static JsonObject getBusLineInfo(String lineCode,int direction) throws IOException {
		JsonObject result = new JsonObject();
		Document doc = Jsoup.connect("http://219.136.133.172:8080/gciOuterNet/information.html?routeCode="+lineCode).get();
		
		Elements elements = doc.select("[bgcolor=#9ac534]").get(direction).select("font");
		JsonArray lineInfo = new JsonArray();
		for(int i=0;i<elements.size();i++){
			String text = elements.get(i).text();
			text = StringUtils.remove(text, " ");
			if(StringUtils.isNotEmpty(text)){
				Logger.debug("text:%s", text);
				lineInfo.add(new JsonPrimitive(text));
			}
		}
		result.add("lineInfo", lineInfo);
		
		
		elements = doc.select("[bgcolor=#0A5420]").get(direction).select("tr").get(0).select("td");
		ArrayList<Integer> numberList = new ArrayList<Integer>();
		for (Element td : elements) {
			Integer num = 0;
			String alt = td.select("img").attr("alt");
			if(StringUtils.isNotEmpty(alt)){				
				Pattern pattern = Pattern.compile("\\d");
				Matcher matcher = pattern.matcher(alt);
				if(matcher.find()){
					String value = matcher.group();
					num = NumberUtils.toInt(value,0);
				}
			}
			Logger.debug("num:%s", num);
			numberList.add(num);
		}
		
		JsonArray siteInfoList = new JsonArray();
		elements = doc.select("[bgcolor=#0A5420]").get(direction).select("tr").get(1).select("td");
		int counter = 0;
		for (Element td : elements){
			String name = td.text();
			Logger.debug("name:%s", td.text());
			if(counter == 0){
				counter++;
				continue;
			}
			JsonObject siteInfo = new JsonObject();
			siteInfo.addProperty("name", name);
			siteInfo.addProperty("num", numberList.get(counter));
			siteInfoList.add(siteInfo);
			counter++;
		}
		
		result.add("details", siteInfoList);
		Logger.debug("details:%s", result.toString());
		return result;
	}
    
}